package xyz.wbsite.dbtool.javafx.manger.callable;

import xyz.wbsite.dbtool.javafx.manger.FreeMarkerManager;
import xyz.wbsite.dbtool.javafx.manger.ManagerFactory;
import xyz.wbsite.dbtool.javafx.manger.XmlManager;
import xyz.wbsite.dbtool.javafx.po.AbstractDBmapper;
import xyz.wbsite.dbtool.javafx.po.DataBase;
import xyz.wbsite.dbtool.javafx.po.Frame;
import xyz.wbsite.dbtool.javafx.po.Module;
import xyz.wbsite.dbtool.javafx.po.MySQLDBmapper;
import xyz.wbsite.dbtool.javafx.po.OracleDBmapper;
import xyz.wbsite.dbtool.javafx.po.Project;
import xyz.wbsite.dbtool.javafx.po.SQLiteDBmapper;
import xyz.wbsite.dbtool.javafx.po.Table;
import xyz.wbsite.dbtool.javafx.po.TableMethod;
import xyz.wbsite.dbtool.javafx.tool.Tool;
import xyz.wbsite.dbtool.javafx.tool.FileUtil;
import xyz.wbsite.dbtool.javafx.tool.ResourceUtil;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.Callable;

public class SpringBootCallable implements Callable {

    private File root;
    private Project project;
    private AbstractDBmapper dBmapper;
    private FreeMarkerManager freeMarkerManager;

    public SpringBootCallable(Project project, File root) {
        this.root = root;
        this.project = project;
        this.freeMarkerManager = ManagerFactory.getFreeMarkerManager();
        // 根据配置获取数据库处理器
        if (project.getDatabase().name().equals(DataBase.MySQL.name())) {
            this.dBmapper = new MySQLDBmapper();
        } else if (project.getDatabase().name().equals(DataBase.Oracle.name())) {
            this.dBmapper = new OracleDBmapper();
        } else if (project.getDatabase().name().equals(DataBase.SQLite.name())) {
            this.dBmapper = new SQLiteDBmapper();
        } else {
            this.dBmapper = new MySQLDBmapper();
        }
    }

    public Boolean call() throws Exception {
        // 创建项目文件夹
        File dir = Tool.createPath(root, project.getName());
        // 清空内容
        Tool.clear(dir);

        // 生成java目录
        File javaDir = Tool.createPath(dir, "src", "main", "java");
        // 生成资源目录
        File resourcesDir = Tool.createPath(dir, "src", "main", "resources");
        // 生成域名目录
        File domainDir = Tool.createPath(javaDir, project.getDomain().split("\\."));
        // 生成单元测试java目录
        File testJavaDir = Tool.createPath(dir, "src", "test", "java");
        // 生成单元测试域名目录
        File testDomainDir = Tool.createPath(testJavaDir, project.getDomain().split("\\."));
        // 生成单元测试resources目录
        File testResourcesDir = Tool.createPath(dir, "src", "test", "resources");

        // 生成POM
        generatePom(dir, project);
        // 生成Application
        System.out.println("生成模块:Application");
        generateApplication(Tool.createPath(domainDir), project);

        System.out.println("生成模块:action");
        generateController(Tool.createPath(domainDir, "action"), project);
        System.out.println("生成模块:config");
        generateConfig(Tool.createPath(domainDir, "config"), project);
        System.out.println("生成模块:frame");
        generateFrame(Tool.createPath(domainDir, "frame"), project);
        System.out.println("生成模块:module");
        generateModule(Tool.createPath(domainDir, "module"), project);
        System.out.println("生成模块:task");
        generateTask(Tool.createPath(domainDir, "task"), project);
        //生成resources文件
        generateResources(resourcesDir, project);

        System.out.println("生成模块:Test");
        generateTest(testDomainDir, project);
        System.out.println("生成模块:Test Resources");
        generateTestResources(testResourcesDir, project);

        System.out.println("finish");
        return true;
    }

    /**
     * 生成POM.xml
     *
     * @param root
     * @param project
     */
    public void generatePom(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("projectName", project.getName());
        ctx.put("domain", project.getDomain());
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("project", project);
        freeMarkerManager.outputTemp(Tool.createFile(root, "pom.xml"), "SpringBoot/pom.ftl", ctx);
    }

    /**
     * 生成Controller类
     *
     * @param root
     * @param project
     */
    public void generateController(File root, Project project) {
        Tool.clear(root);
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("project", project);
        ctx.put("domain", project.getDomain());
        ctx.put("author", project.getAuthor());
        ctx.put("modules", project.getModules());

        //region Page
        if (project.isNeedHtml()) {
            File control = Tool.createPath(root, "page", "control");
            freeMarkerManager.outputTemp(Tool.createFile(control, "Header.java"), "SpringBoot/java/action/page/control/Header.java", ctx);

            File screen = Tool.createPath(root, "page", "screen");
            freeMarkerManager.outputTemp(Tool.createFile(screen, "Index.java"), "SpringBoot/java/action/page/screen/Index.java", ctx);
        }
        //endregion

        //region 异步接口
        if (project.isNeedAjax()) {
            File ajax = Tool.createPath(root, "ajax");
            HashMap<String, Object> ctxss = new HashMap<String, Object>();
            ctxss.put("domain", project.getDomain());
            ctxss.put("author", project.getAuthor());

            for (Module module : project.getModules()) {
                if (!module.getNeedGenerate()) {
                    continue;
                }
                File m = Tool.createPath(ajax, module.getName());
                ctxss.put("moduleName", module.getName());
                for (Table table : module.getTables()) {
                    if (table.isAjax()) {
                        ctxss.put("table", table);
                        freeMarkerManager.outputTemp(Tool.createFile(m, table.getCName() + "Ajax.java"), "SpringBoot/java/action/ajax/Ajax.java", ctxss);
                    }
                }
            }

            if (project.getFrame().value() == Frame.基础框架.value()) {//管理架构
                File wsys = Tool.createPath(ajax, "wsys");
                for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/action/ajax/wsys/")) {
                    freeMarkerManager.outputTemp(Tool.createFile(wsys, name), "SpringBoot/java/action/ajax/wsys/" + name, ctx);
                }
            }
        }
        //endregion

        //region 应用接口
        if (project.isNeedApi()) {
            File api = Tool.createPath(root, "api");

            for (Module module : project.getModules()) {
                if (!module.getNeedGenerate()) {
                    continue;
                }
                HashMap<String, Object> ctxss = new HashMap<String, Object>();
                ctxss.put("project", project);
                ctxss.put("domain", project.getDomain());
                ctxss.put("author", project.getAuthor());
                ctxss.put("module", module.getName());
                File m = Tool.createPath(api, module.getName());
                for (Table table : module.getTables()) {
                    if (table.getApi()) {
                        ctxss.put("table", table);
                        freeMarkerManager.outputTemp(Tool.createFile(m, table.getCName() + "Api.java"), "SpringBoot/java/action/api/Api.java", ctxss);
                    }
                }
            }

            if (project.getFrame().value() >= Frame.基础框架.value()) {//生成系统模块
                File wsys = Tool.createPath(api, "wsys");

                for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/action/api/wsys/")) {
                    freeMarkerManager.outputTemp(Tool.createFile(wsys, name), "SpringBoot/java/action/api/wsys/" + name, ctx);
                }
            }
        }
        //endregion

        //region 微服务接口
        if (project.isNeedCloud()) {
            File msvr = Tool.createPath(root, "msvr");
            for (Module module : project.getModules()) {
                if (!module.getNeedGenerate()) {
                    continue;
                }
                HashMap<String, Object> ctxss = new HashMap<String, Object>();
                ctxss.put("project", project);
                ctxss.put("domain", project.getDomain());
                ctxss.put("author", project.getAuthor());
                ctxss.put("module", module.getName());
                File m = Tool.createPath(msvr, module.getName());
                for (Table table : module.getTables()) {
                    if (!table.getMsvr()) {
                        continue;
                    }
                    ctxss.put("table", table);
                    freeMarkerManager.outputTemp(Tool.createFile(m, table.getCName() + "Msvr.java"), "SpringBoot/java/action/msvr/Msvr.java", ctxss);
                }
            }
        }
        //endregion

        freeMarkerManager.outputTemp(Tool.createFile(root, "GlobalController.java"), "SpringBoot/java/action/GlobalController.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "GlobalErrorController.java"), "SpringBoot/java/action/GlobalErrorController.java", ctx);
    }

    public void generateConfig(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("project", project);
        ctx.put("domain", project.getDomain());
        ctx.put("projectName", project.getName());
        ctx.put("author", project.getAuthor());

        //config
        freeMarkerManager.outputTemp(Tool.createFile(root, "FreeMarkerConfig.java"), "SpringBoot/java/config/FreeMarkerConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "WebMvcConfig.java"), "SpringBoot/java/config/WebMvcConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "CacheConfig.java"), "SpringBoot/java/config/CacheConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "SecurityConfig.java"), "SpringBoot/java/config/SecurityConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "ActionConfig.java"), "SpringBoot/java/config/ActionConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "TaskConfig.java"), "SpringBoot/java/config/TaskConfig.java", ctx);
        if (project.isNeedAsync()) {
            freeMarkerManager.outputTemp(Tool.createFile(root, "ThreadPoolConfig.java"), "SpringBoot/java/config/ThreadPoolConfig.java", ctx);
        }
        if (project.getDatabase().name().equals(DataBase.SQLite.name())) {
            freeMarkerManager.outputTemp(Tool.createFile(root, "SQLiteConfig.java"), "SpringBoot/java/config/SQLiteConfig.java", ctx);
        }
        if (project.isNeedMoreDB()) {
            freeMarkerManager.outputTemp(Tool.createFile(root, "MapperMainConfig.java"), "SpringBoot/java/config/MapperMainConfig.java", ctx);
            freeMarkerManager.outputTemp(Tool.createFile(root, "MapperTwoConfig.java"), "SpringBoot/java/config/MapperTwoConfig.java", ctx);
        }
        if (project.isNeedCloud()) {
            freeMarkerManager.outputTemp(Tool.createFile(root, "CloudConfig.java"), "SpringBoot/java/config/CloudConfig.java", ctx);
        }
    }

    public void generateModule(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }

        for (Module module : project.getModules()) {// 业务模块
            if (!module.getNeedGenerate()) {
                continue;
            }
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("project", project);
            ctx.put("module", module);
            ctx.put("domain", project.getDomain());
            ctx.put("author", project.getAuthor());
            ctx.put("moduleName", module.getName());
            ctx.put("dataBase", project.getDatabase().toString());

            File ent = Tool.createPath(Tool.createPath(root, module.getName()), "ent");
            File mpr = Tool.createPath(Tool.createPath(root, module.getName()), "mpr");
            File mgr = Tool.createPath(Tool.createPath(root, module.getName()), "mgr");
            File svr = null;
            if (project.isNeedCloud()) {
                svr = Tool.createPath(Tool.createPath(root, module.getName()), "svr");
            }
            File req = Tool.createPath(Tool.createPath(root, module.getName()), "req");
            File rsp = Tool.createPath(Tool.createPath(root, module.getName()), "rsp");

            module.setProjectAuthor(project.getAuthor());
            module.setProjectBasePackage(project.getDomain());
            module.setProjectName(project.getName());

            for (Table table : module.getTables()) {
                ctx.put("table", table);

                // 生成Ent
                File file = Tool.createFile(ent, Tool.ABB2Abb(table.getTableName()) + ".java");
                freeMarkerManager.outputTemp(file, "SpringBoot/java/module/ent/entity.ftl", ctx);

                // 生成Mapper
                if (table.getSys()) {
                    freeMarkerManager.outputTemp(Tool.createFile(mpr, Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".java"), "SpringBoot/java/module/mpr/Mapper.java", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(mpr, Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".xml"), "SpringBoot/java/module/mpr/" + project.getDatabase().name() + "_mapper.xml", ctx);
                } else {
                    freeMarkerManager.outputTemp(Tool.createFile(mpr, Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".java"), "SpringBoot/java/module/mpr/Mapper_NSYS.java", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(mpr, Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".xml"), "SpringBoot/java/module/mpr/" + project.getDatabase().name() + "_NSYS_mapper.xml", ctx);
                }

                if (table.getSys()) {
                    freeMarkerManager.outputTemp(Tool.createFile(mgr, Tool.ABB2Abb(table.getTableName()) + "Manager" + ".java"), "SpringBoot/java/module/mgr/manager.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(mgr, Tool.ABB2Abb(table.getTableName()) + "ManagerImpl" + ".java"), "SpringBoot/java/module/mgr/managerImpl.ftl", ctx);
                } else {
                    freeMarkerManager.outputTemp(Tool.createFile(mgr, Tool.ABB2Abb(table.getTableName()) + "Manager" + ".java"), "SpringBoot/java/module/mgr/manager_NSYS.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(mgr, Tool.ABB2Abb(table.getTableName()) + "ManagerImpl" + ".java"), "SpringBoot/java/module/mgr/managerImpl_NSYS.ftl", ctx);
                }

                if (project.isNeedCloud()) {
                    freeMarkerManager.outputTemp(Tool.createFile(svr, Tool.ABB2Abb(table.getTableName()) + "Service" + ".java"), "SpringBoot/java/module/svr/Service.java", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(svr, Tool.ABB2Abb(table.getTableName()) + "ServiceImpl" + ".java"), "SpringBoot/java/module/svr/ServiceImpl.java", ctx);
                }

                if (table.getCreate()) {
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + "CreateRequest" + ".java"), "SpringBoot/java/module/req/createRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + "CreateResponse" + ".java"), "SpringBoot/java/module/rsp/createResponseClass.ftl", ctx);
                }

                if (table.getDelete()) {
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + "DeleteRequest" + ".java"), "SpringBoot/java/module/req/deleteRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + "DeleteResponse" + ".java"), "SpringBoot/java/module/rsp/deleteResponseClass.ftl", ctx);
                }

                if (table.getUpdate()) {
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + "UpdateRequest" + ".java"), "SpringBoot/java/module/req/updateRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + "UpdateResponse" + ".java"), "SpringBoot/java/module/rsp/updateResponseClass.ftl", ctx);
                }

                if (table.getFind()) {
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + "FindRequest" + ".java"), "SpringBoot/java/module/req/findRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + "FindResponse" + ".java"), "SpringBoot/java/module/rsp/findResponseClass.ftl", ctx);
                }

                if (table.getGet()) {
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + "GetRequest" + ".java"), "SpringBoot/java/module/req/getRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + "GetResponse" + ".java"), "SpringBoot/java/module/rsp/getResponseClass.ftl", ctx);
                }

                if (table.getSearch()) {
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + "SearchRequest" + ".java"), "SpringBoot/java/module/req/searchRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + "SearchResponse" + ".java"), "SpringBoot/java/module/rsp/searchResponseClass.ftl", ctx);
                }

                for (TableMethod tableMethod : table.getMethods()) {
                    String method = Tool.abb2Abb(tableMethod.getName());
                    ctx.put("method", method);
                    ctx.put("methodNote", tableMethod.getNote());
                    freeMarkerManager.outputTemp(Tool.createFile(req, Tool.ABB2Abb(table.getTableName()) + method + "Request" + ".java"), "SpringBoot/java/module/req/methodRequestClass.ftl", ctx);
                    freeMarkerManager.outputTemp(Tool.createFile(rsp, Tool.ABB2Abb(table.getTableName()) + method + "Response" + ".java"), "SpringBoot/java/module/rsp/methodResponseClass.ftl", ctx);
                }
            }
        }

        Module module = tryGetModule(project, "wsys");
        if (module == null || !module.getNeedGenerate()) {// 生成系统模块
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("project", project);
            ctx.put("domain", project.getDomain());
            ctx.put("moduleName", "wsys");
            ctx.put("author", project.getAuthor());
            ctx.put("dataBase", project.getDatabase().toString());

            File ent = Tool.createPath(root, "wsys", "ent");
            File mpr = Tool.createPath(root, "wsys", "mpr");
            File mgr = Tool.createPath(root, "wsys", "mgr");
            File req = Tool.createPath(root, "wsys", "req");
            File rsp = Tool.createPath(root, "wsys", "rsp");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/module/wsys/ent/")) {
                freeMarkerManager.outputTemp(Tool.createFile(ent, name), "SpringBoot/java/module/wsys/ent/" + name, ctx);
            }

            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/module/wsys/mgr/")) {
                freeMarkerManager.outputTemp(Tool.createFile(mgr, name), "SpringBoot/java/module/wsys/mgr/" + name, ctx);
            }

            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/module/wsys/mpr/")) {
                if (name.endsWith(".java")) {
                    freeMarkerManager.outputTemp(Tool.createFile(mpr, name), "SpringBoot/java/module/wsys/mpr/" + name, ctx);
                } else if (name.contains(project.getDatabase().name())) {
                    freeMarkerManager.outputTemp(Tool.createFile(mpr, name.replaceAll(project.getDatabase().name() + "_", "")), "SpringBoot/java/module/wsys/mpr/" + name, ctx);
                }
            }

            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/module/wsys/req/")) {
                freeMarkerManager.outputTemp(Tool.createFile(req, name), "SpringBoot/java/module/wsys/req/" + name, ctx);
            }

            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/module/wsys/rsp/")) {
                freeMarkerManager.outputTemp(Tool.createFile(rsp, name), "SpringBoot/java/module/wsys/rsp/" + name, ctx);
            }
        }
    }

    /**
     * 生成frame类
     *
     * @param root
     * @param project
     */
    public void generateFrame(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("project", project);
        ctx.put("domain", project.getDomain());
        ctx.put("moduleName", project.getName());
        ctx.put("timestamp", new Date().getTime());

        //auth
        {
            File auth = Tool.createPath(root, "auth");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/auth/")) {
                freeMarkerManager.outputTemp(Tool.createFile(auth, name), "SpringBoot/java/frame/auth/" + name, ctx);
            }
        }

        //base
        {
            File base = Tool.createPath(root, "base");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/base/")) {
                freeMarkerManager.outputTemp(Tool.createFile(base, name), "SpringBoot/java/frame/base/" + name, ctx);
            }
        }

        //utils
        {
            File utils = Tool.createPath(root, "utils");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/utils/")) {
                freeMarkerManager.outputTemp(Tool.createFile(utils, name), "SpringBoot/java/frame/utils/" + name, ctx);
            }
        }

        //schedule
        {
            File schedule = Tool.createPath(root, "schedule");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/schedule/")) {
                freeMarkerManager.outputTemp(Tool.createFile(schedule, name), "SpringBoot/java/frame/schedule/" + name, ctx);
            }
        }

        //sse
        {
            File sse = Tool.createPath(root, "sse");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/sse/")) {
                freeMarkerManager.outputTemp(Tool.createFile(sse, name), "SpringBoot/java/frame/sse/" + name, ctx);
            }
        }

        {//excel
            File excel = Tool.createPath(root, "excel");
            File excelannotation = Tool.createPath(excel, "annotation");
            File excelconverter = Tool.createPath(excel, "converter");
            File exception = Tool.createPath(excel, "exception");
            File excelhandler = Tool.createPath(excel, "handler");
            File excellistener = Tool.createPath(excel, "listener");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/excel/")) {
                freeMarkerManager.outputTemp(Tool.createFile(excel, name), "SpringBoot/java/frame/excel/" + name, ctx);
            }
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/excel/annotation/")) {
                freeMarkerManager.outputTemp(Tool.createFile(excelannotation, name), "SpringBoot/java/frame/excel/annotation/" + name, ctx);
            }
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/excel/converter/")) {
                freeMarkerManager.outputTemp(Tool.createFile(excelconverter, name), "SpringBoot/java/frame/excel/converter/" + name, ctx);
            }
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/excel/exception/")) {
                freeMarkerManager.outputTemp(Tool.createFile(exception, name), "SpringBoot/java/frame/excel/exception/" + name, ctx);
            }
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/excel/handler/")) {
                freeMarkerManager.outputTemp(Tool.createFile(excelhandler, name), "SpringBoot/java/frame/excel/handler/" + name, ctx);
            }
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/excel/listener/")) {
                freeMarkerManager.outputTemp(Tool.createFile(excellistener, name), "SpringBoot/java/frame/excel/listener/" + name, ctx);
            }
        }

        //mail
        if (project.isNeedEMail()) {
            File mail = Tool.createPath(root, "mail");
            File message = Tool.createPath(mail, "message");
            freeMarkerManager.outputTemp(Tool.createFile(mail, "WMailSender.java"), "SpringBoot/java/frame/mail/WMailSender.java", ctx);
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/mail/message/")) {
                freeMarkerManager.outputTemp(Tool.createFile(message, name), "SpringBoot/java/frame/mail/message/" + name, ctx);
            }
        }

        //validation
        {
            File validation = Tool.createPath(root, "validation");
            for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/frame/validation/")) {
                freeMarkerManager.outputTemp(Tool.createFile(validation, name), "SpringBoot/java/frame/validation/" + name, ctx);
            }
        }
    }

    /**
     * 生成Task类
     *
     * @param root
     * @param project
     */
    public void generateTask(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("domain", project.getDomain());
        ctx.put("moduleName", project.getName());

        //task
        for (String name : ResourceUtil.listFileName("/modules/SpringBoot/java/task/")) {
            freeMarkerManager.outputTemp(Tool.createFile(root, name), "SpringBoot/java/task/" + name, ctx);
        }
    }

    /**
     * 生成base类
     *
     * @param root
     * @param project
     */
    public void generateApplication(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("domain", project.getDomain());
        ctx.put("project", project);
        freeMarkerManager.outputTemp(Tool.createFile(root, "Application.java"), "SpringBoot/java/Application.ftl", ctx);
    }

    /**
     * 生成Resources
     *
     * @param root
     * @param project
     */
    public void generateResources(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("domain", project.getDomain());
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("author", project.getAuthor());
        ctx.put("dBmapper", dBmapper);
        ctx.put("author", project.getAuthor());
        ctx.put("project", project);

        //region 日志配置，脚本配置
        freeMarkerManager.outputTemp(Tool.createFile(root, "application.properties"), "SpringBoot/resources/application.ftl", ctx);

        freeMarkerManager.outputTemp(Tool.createFile(root, "start-dev.bat"), "SpringBoot/resources/start-dev.bat", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "start-prod.bat"), "SpringBoot/resources/start-prod.bat", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "application-dev.properties"), "SpringBoot/resources/application-dev.ftl", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root, "application-prod.properties"), "SpringBoot/resources/application-prod.ftl", ctx);
        Tool.outputResource("SpringBoot/resources/logback-spring-dev.xml", Tool.createFile(root, "logback-spring-dev.xml"));
        Tool.outputResource("SpringBoot/resources/logback-spring-prod.xml", Tool.createFile(root, "logback-spring-prod.xml"));
        //endregion

        //region 项目设计文件及SQL
        File dbtool = Tool.createPath(root, "dbtool");
        {
            XmlManager xmlManager = ManagerFactory.getXmlManager();
            xmlManager.saveAs(dbtool, project);
        }

        for (Module module : project.getModules()) {
            if (module.getNeedGenerate()) {
                ctx.put("moduleName", module.getName());
                ctx.put("module", module);
                File tableDir = Tool.createPath(dbtool, module.getName() + "_table");
                for (Table table : module.getTables()) {
                    ctx.put("table", table);
                    freeMarkerManager.outputTemp(Tool.createFile(tableDir, project.getDatabase().name() + "_" + table.getTableName() + ".sql"), "SpringBoot/resources/dbtool/table.ftl", ctx);
                }
                freeMarkerManager.outputTemp(Tool.createFile(tableDir, project.getDatabase().name() + "_ALL_TABLE" + ".sql"), "SpringBoot/resources/dbtool/tableAll.ftl", ctx);
            }
        }

        if (project.getFrame().value() == Frame.基础框架.value()) {
            Module wsysModule = tryGetModule(project, "wsys");
            if (wsysModule == null || !wsysModule.getNeedGenerate()) {// 覆盖
                File wsys = Tool.createPath(dbtool, "wsys_table");

                for (String name : ResourceUtil.listFileName("/modules/SpringBoot/resources/dbtool/wsys_table/")) {
                    if (name.contains(project.getDatabase().name())) {
                        freeMarkerManager.outputTemp(Tool.createFile(wsys, name), "SpringBoot/resources/dbtool/wsys_table/" + name, ctx);
                    }
                }
            }
        }
        //endregion


        //region SQLite数据库模板生成
        if (DataBase.SQLite.name().equals(project.getDatabase().name())) {
            File old = new File(root, project.getName() + ".db3");
            if (old.exists()){
                old.delete();
            }
            File dbFile = Tool.createFile(root, project.getName() + ".db3");
            Connection connection = null;
            Statement statement = null;
            try {
                Class.forName("org.sqlite.JDBC");
                connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile);

                for (File fileModule : dbtool.listFiles()) {
                    if (!fileModule.isDirectory()) {
                        continue;
                    }
                    for (File file : fileModule.listFiles()) {
                        if (file.getName().startsWith("SQLite_") && !file.getName().startsWith("SQLite_ALL_") && file.getName().endsWith(".sql")) {
                            statement = connection.createStatement();
                            String sql = FileUtil.readFileToString(file);
                            statement.execute(sql);
                            statement.close();
                        }
                    }
                }
            } catch (ClassNotFoundException | SQLException | IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (statement != null) statement.close();
                    if (connection != null) connection.close();
                } catch (Exception e) {

                }
            }
        }
        //endregion

        //region 只有默认选中网页服务的情况下才需要 生成static和template
        if (project.isNeedHtml()) {
            System.out.println("生成模块:Static");
            File static_ = Tool.createPath(root, "static");
            File css = Tool.createPath(static_, "css");
            File img = Tool.createPath(static_, "img");
            File dist = Tool.createPath(static_, "dist");
            File echarts = Tool.createPath(dist, "echarts");
            Tool.outputResource("SpringBoot/resources/static/favicon.ico", Tool.createFile(static_, "favicon.ico"));

            //css文件
            freeMarkerManager.outputTemp(Tool.createFile(css, "base.css"), "SpringBoot/resources/static/css/base.css", ctx);

            //img
            Tool.outputResource("SpringBoot/resources/static/img/logo.png", Tool.createFile(img, "logo.png"));

            // dist文件jquery + vue + vue-router + axios
            Tool.outputResource("SpringBoot/resources/static/dist/lib.min.js", Tool.createFile(dist, "lib.min.js"));

            //element-ui
            Tool.outputResource("SpringBoot/resources/static/dist/index.min.js", Tool.createFile(dist, "index.min.js"));
            Tool.outputResource("SpringBoot/resources/static/dist/index.min.css", Tool.createFile(dist, "index.min.css"));

            //element-ui
            Tool.outputResource("SpringBoot/resources/static/dist/echarts/echarts.js", Tool.createFile(echarts, "echarts.js"));
            Tool.outputResource("SpringBoot/resources/static/dist/echarts/echarts.min.js", Tool.createFile(echarts, "echarts.min.js"));

            File fonts = Tool.createPath(dist, "fonts");
//            Tool.outputResource("SpringBoot/resources/static/dist/fonts/w-e-icon.woff", Tool.createFile(fonts, "w-e-icon.woff"));
            Tool.outputResource("SpringBoot/resources/static/dist/fonts/element-icons.woff", Tool.createFile(fonts, "element-icons.woff"));
            Tool.outputResource("SpringBoot/resources/static/dist/fonts/element-icons.ttf", Tool.createFile(fonts, "element-icons.ttf"));

            System.out.println("生成模块:Templates");
            File templates = Tool.createPath(root, "templates");
            File control = Tool.createPath(templates, "control");
            File layout = Tool.createPath(templates, "layout");
            File screen = Tool.createPath(templates, "screen");
            Tool.outputResource("SpringBoot/resources/templates/control/nav.ftl", Tool.createFile(control, "nav.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/control/macro.ftl", Tool.createFile(control, "macro.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/layout/default.ftl", Tool.createFile(layout, "default.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/layout/home.ftl", Tool.createFile(layout, "home.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/screen/home.ftl", Tool.createFile(screen, "home.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/screen/help.ftl", Tool.createFile(screen, "help.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/screen/helpDev.ftl", Tool.createFile(screen, "helpDev.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/screen/login.ftl", Tool.createFile(screen, "login.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/403.ftl", Tool.createFile(templates, "403.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/404.ftl", Tool.createFile(templates, "404.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/500.ftl", Tool.createFile(templates, "500.ftl"));

            freeMarkerManager.outputTemp(Tool.createFile(screen, "index.ftl"), "SpringBoot/resources/templates/screen/index.ftl", ctx);

            for (Module module : project.getModules()) {
                if (module.getNeedGenerate()) {
                    File modulePath = Tool.createPath(screen, module.getName());
                    for (Table table : module.getTables()) {
                        if (table.isPage()) {
                            ctx.put("table", table);
                            ctx.put("module", module);
                            ctx.put("fields", table.getFields());
                            File file = Tool.createFile(modulePath, table.getFName() + ".ftl");
                            freeMarkerManager.outputTemp(file, "SpringBoot/resources/templates/screen/module/mgr.ftl", ctx);
                        }
                    }
                }
            }

            //生成网页
            if (project.getFrame().value() == Frame.基础框架.value()) {
                Module wsysModule = tryGetModule(project, "wsys");// 防止与系统冲突，一般不会重复，通常是架构重新设计时遇到
                if (wsysModule == null || !wsysModule.getNeedGenerate()) {
                    File wsys = Tool.createPath(screen, "wsys");
                    for (String name : ResourceUtil.listFileName("/modules/SpringBoot/resources/templates/screen/module/wsys/")) {
                        Tool.outputResource("SpringBoot/resources/templates/screen/module/wsys/" + name, Tool.createFile(wsys, name));
                    }
                }
            }
        }
        //endregion
    }

    public void generateTestResources(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();

        ctx.put("domain", project.getDomain());
        ctx.put("projectName", project.getName());
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("author", project.getAuthor());
        ctx.put("dBmapper", dBmapper);
        ctx.put("project", project);
        freeMarkerManager.outputTemp(Tool.createFile(root, "application.properties"), "SpringBoot/test/application.ftl", ctx);
        Tool.outputResource("SpringBoot/test/logback-spring.xml", Tool.createFile(root, "logback-spring.xml"));
    }

    public void generateTest(File root, Project project) {
        {
            File config = Tool.createPath(root, "config");
            config.mkdirs();
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", project.getDomain());
            ctx.put("moduleName", project.getName());
            ctx.put("author", project.getAuthor());
            File file = Tool.createFile(config, "TestConfig" + ".java");
            freeMarkerManager.outputTemp(file, "SpringBoot/test/TestConfig.ftl", ctx);
        }

        {
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", project.getDomain());
            ctx.put("moduleName", project.getName());
            ctx.put("author", project.getAuthor());
            File frame = Tool.createPath(root, "frame");
            freeMarkerManager.outputTemp(Tool.createFile(frame, "ExcelTest.java"), "SpringBoot/test/frame/ExcelTest.java", ctx);
            if (project.isNeedEMail()) {
                freeMarkerManager.outputTemp(Tool.createFile(frame, "MailTest.java"), "SpringBoot/test/frame/MailTest.java", ctx);
            }
            freeMarkerManager.outputTemp(Tool.createFile(frame, "UtilTest.java"), "SpringBoot/test/frame/UtilTest.java", ctx);
        }

        for (Module md : project.getModules()) {
            if (md.getNeedGenerate()) {
                File module = Tool.createPath(root, md.getName());

                for (Table table : md.getTables()) {
                    HashMap<String, Object> ctx = new HashMap<String, Object>();

                    ctx.put("domain", project.getDomain());
                    ctx.put("module", md);
                    ctx.put("moduleName", md.getName());
                    ctx.put("table", table);
                    ctx.put("author", md.getProjectAuthor());

                    File file = Tool.createFile(module, Tool.ABB2Abb(table.getTableName()) + "Test" + ".java");
                    freeMarkerManager.outputTemp(file, "SpringBoot/test/test.ftl", ctx);
                }
            }
        }


        if (project.getFrame().value() == Frame.基础框架.value()) {
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", project.getDomain());
            ctx.put("moduleName", project.getName());
            ctx.put("author", project.getAuthor());
            ctx.put("project", project);
            File wsys = Tool.createPath(root, "wsys");

            for (String apiFile : ResourceUtil.listFileName("/modules/SpringBoot/test/wsys/")) {
                freeMarkerManager.outputTemp(Tool.createFile(wsys, apiFile), "SpringBoot/test/wsys/" + apiFile, ctx);
            }
            freeMarkerManager.outputTemp(Tool.createFile(root, "DataInit.java"), "SpringBoot/test/DataInit.java", ctx);
        }
    }

    private Module tryGetModule(Project project, String moduleName) {
        for (Module module : project.getModules()) {
            if (module.getName().equals(moduleName)) {
                return module;
            }
        }
        return null;
    }

}
